package com.spic.business.violation.supervision.information.service.impl;

import com.deepoove.poi.XWPFTemplate;
import com.spic.business.common.core.workflow.IWorkFlowType;
import com.spic.business.common.datascope.anotation.BusinessDataScope;
import com.spic.business.common.workflow.WorkFlowServiceImpl;
import com.spic.business.enumconst.BusinessType;
import com.spic.business.getui.service.PushService;
import com.spic.business.train.plan.domain.TrainPlan;
import com.spic.business.train.plan.domain.TrainPlanShift;
import com.spic.business.train.plan.domain.TrainPlanStaff;
import com.spic.business.train.plan.service.ITrainPlanService;
import com.spic.business.utils.GroupUtils;
import com.spic.business.violation.supervision.information.domain.ViolationInformation;
import com.spic.business.violation.supervision.information.domain.ViolationInformationDirty;
import com.spic.business.violation.supervision.information.mapper.ViolationInformationDirtyMapper;
import com.spic.business.violation.supervision.information.mapper.ViolationInformationMapper;
import com.spic.business.violation.supervision.information.service.IViolationInformationService;
import com.spic.common.core.domain.R;
import com.spic.common.core.exception.ServiceException;
import com.spic.common.core.utils.DateUtils;
import com.spic.common.core.utils.IdUtils;
import com.spic.common.core.utils.SecurityUtils;
import com.spic.common.core.utils.StringUtils;
import com.spic.common.core.utils.bean.BeanUtils;
import com.spic.common.core.web.controller.BaseController;
import com.spic.common.core.web.domain.AjaxResult;
import com.spic.common.log.enums.BusinessStatus;
import com.spic.system.api.RemoteDeptService;
import com.spic.system.api.RemoteFileService;
import com.spic.system.api.RemoteNoticeInfoService;
import com.spic.system.api.RemoteUserService;
import com.spic.system.api.domain.SysFile;
import com.spic.system.api.domain.SysNoticeInfo;
import com.spic.system.api.domain.SysUser;
import org.apache.commons.compress.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 违章举报Service业务层处理
 *
 * @author spic
 * @date 2021-10-14
 */
@Service
public class ViolationInformationServiceImpl extends WorkFlowServiceImpl<ViolationInformationMapper, ViolationInformation> implements IViolationInformationService {
    @Autowired
    private ViolationInformationMapper violationInformationMapper;
    @Autowired
    private RemoteDeptService remoteDeptService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteNoticeInfoService remoteNoticeInfoService;
    @Autowired
    private PushService doPush;

    @Autowired
    private RemoteFileService remoteFileService;
    @Autowired
    private ThreadPoolExecutor execute;
    @Autowired
    private ViolationInformationDirtyMapper violationInformationDirtyMapper;
    @Autowired
    private ITrainPlanService trainPlanService;


    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 查询违章举报
     *
     * @param id 违章举报主键
     * @return 违章举报
     */
    @Override
    public ViolationInformation selectViolationInformationById(Long id) {
        return violationInformationMapper.selectViolationInformationById(id);
    }

    /**
     * 查询违章举报列表
     *
     * @param violationInformation 违章举报
     * @return 违章举报
     */
    @Override
    @BusinessDataScope(menuPath = "business/violation/information/index")
    public List<ViolationInformation> selectViolationInformationList(ViolationInformation violationInformation) {
        List<ViolationInformation> violationInformations = violationInformationMapper.selectViolationInformationList(violationInformation);
        super.processRow(violationInformations, null);
        return violationInformations;

    }

    /**
     * 新增违章举报
     *
     * @param violationInformation 违章举报
     * @return 结果
     */
    @Override
    public Long insertViolationInformation(ViolationInformation violationInformation) {
        Long userId = SecurityUtils.getUserId();
        violationInformation.setMentionDissolution(userId.toString());
        violationInformation.setCreateTime(DateUtils.getNowDate());
        violationInformation.setIllegalSources("违章举报");
        violationInformationMapper.insertViolationInformation(violationInformation);
        Long id = violationInformation.getId();
        return id;
    }

    /**
     * 修改违章举报
     *
     * @param violationInformation 违章举报
     * @return 结果
     */
    @Override
    public int updateViolationInformation(ViolationInformation violationInformation) {
        violationInformation.setUpdateTime(DateUtils.getNowDate());
        if(StringUtils.isNotEmpty(violationInformation.getHrUserId())) {
            noticeInfo(violationInformation, violationInformation.getHrUserId(), new Date());
        }
        return violationInformationMapper.updateViolationInformation(violationInformation);
    }

    /**
     * 推送消息
     */
    public void noticeInfo(ViolationInformation violationInfo, String hrUserId, Date date){
        ViolationInformation violationInformation = selectViolationInformationById(violationInfo.getId());
        String associatedDept = violationInformation.getAssociatedDept();
        String deptName = remoteDeptService.getDeptName(Long.valueOf(associatedDept)).getData();
        SysUser sysUser = remoteUserService.getUserById(Long.valueOf(violationInformation.getResponsible())).getData();
        SysNoticeInfo info = new SysNoticeInfo();
        StringBuilder content = new StringBuilder();
        content.append(deptName + "单位的" + sysUser.getNickName() + "违章，违章原因：" + violationInformation.getIllegalInstructions());
        content.append("，请对该责任人扣罚奖金");
        if("N".equals(violationInformation.getStaffType())) {
            content.append("，根据被处罚金额，扣除综合绩效考核" + violationInformation.getDeduction() + "分。");
        }
        info.setContent(content.toString());
        info.setTitle("安全监察处罚通知单");
        info.setUserId(hrUserId);
        info.setCreateBy(hrUserId);
        info.setCreateTime(date);
        remoteNoticeInfoService.add(info);
//        String cid = remoteUserService.getUserById(new Long(userId)).getData().getCid();
//        Integer clientType = remoteUserService.getUserById(new Long(userId)).getData().getClientType();
//        if(StringUtils.isNotEmpty(cid)){
//            doPush.push(cid, "安全监察处罚通知单","安全监察处罚通知单财务已审核，请知晓", clientType);
//        }
    }

    /**
     * 批量删除违章举报
     *
     * @param ids 需要删除的违章举报主键
     * @return 结果
     */
    @Override
    public int deleteViolationInformationByIds(Long[] ids) {
        return violationInformationMapper.deleteViolationInformationByIds(ids);
    }

    /**
     * 删除违章举报信息
     *
     * @param id 违章举报主键
     * @return 结果
     */
    @Override
    public int deleteViolationInformationById(Long id) {
        return violationInformationMapper.deleteViolationInformationById(id);
    }

    @Override
    public List<HashMap<String, Object>> getillegalSourceCount(ViolationInformation violationInformation) {
        return violationInformationMapper.getillegalSourceCount(violationInformation);
    }

    @Override
    public List<HashMap<String, Object>> getillegalTypeCount(ViolationInformation violationInformation) {
        return violationInformationMapper.getillegalTypeCount(violationInformation);
    }

    @Override
    public List<HashMap<String, Object>> getillegalAreaCount(ViolationInformation violationInformation) {
        return violationInformationMapper.getillegalAreaCount(violationInformation);
    }

    @Override
    public void downloadReport(Long id, HttpServletResponse response) {
        InputStream inputStream = null;
        ServletOutputStream servletOutputStream = null;
        ClassPathResource classPathResource = null;
        try {
            ViolationInformation violationInformation = selectViolationInformationById(id);
            Map<String, Object> texts = new HashMap<>();
            String associatedDept = violationInformation.getAssociatedDept();
            String deptName = remoteDeptService.getDeptName(Long.valueOf(associatedDept)).getData();
            SysUser sysUser = remoteUserService.getUserById(Long.valueOf(violationInformation.getResponsible())).getData();

            texts.put("associatedDept", deptName);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
            texts.put("illegalTime", simpleDateFormat.format(violationInformation.getIllegalTime()));
            texts.put("responsible", sysUser.getNickName());
            texts.put("illegalInstructions", violationInformation.getIllegalInstructions());
            texts.put("punishJustify", violationInformation.getPunishJustify());
            texts.put("associatedDept_1", deptName);
            texts.put("penaltyAmount", violationInformation.getPenaltyAmount());
            texts.put("associatedDept_2", deptName);
            texts.put("responsible_1", sysUser.getNickName());
            texts.put("deduction", violationInformation.getDeduction());

            if("Y".equals(violationInformation.getStaffType())) {
                classPathResource = new ClassPathResource("Excel_model/punishTemplate_own.docx");
            } else {
                classPathResource = new ClassPathResource("Excel_model/punishTemplate_contractor.docx");
            }
            inputStream = classPathResource.getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(inputStream).render(texts);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/force-download");// 设置强制下载不打开
            String title = "处罚通知单_" + IdUtils.fastSimpleUUID();
            title += ".docx";
            response.setHeader("Content-Disposition", "attach;filename=" + new String(title.getBytes(StandardCharsets.UTF_8) , StandardCharsets.ISO_8859_1));

            File tempFile = File.createTempFile("xxx", ".docx");

            try{
                OutputStream outputStream = response.getOutputStream();
                template.render(texts);

                //文件上传到MinIO
                if(StringUtils.isEmpty(violationInformation.getFileUrl())) {
                    try {
                        FileOutputStream fop = new FileOutputStream(tempFile);
                        template.write(fop);
                        MultipartFile multipartFile = new MockMultipartFile("punish.docx", tempFile.getName(),
                                "application/vnd.openxmlformats-officedocument.wordprocessingml.document", new FileInputStream(tempFile));
                        R<SysFile> fileResult = remoteFileService.upload(multipartFile);
                        violationInformation.setFileUrl(fileResult.getData().getUrl());
                        updateViolationInformation(violationInformation);
                    } catch (Exception e) {
                        logger.error(e.getMessage());
                    }
                }
                template.writeAndClose(outputStream);
            }
            catch (IOException e)
            {
                logger.error("download check report fail: " + e.getMessage());
            } finally {
                if (tempFile != null) {
                    tempFile.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("exception: " + e.getMessage());
        } finally {
            IOUtils.closeQuietly(servletOutputStream);
            IOUtils.closeQuietly(inputStream);
        }
    }

    @Override
    protected IWorkFlowType getWorkFlowType() {
        return BusinessType.VIOLATION_INFORMATION;
    }

    @Override
    protected void setWorkFlowVariable(ViolationInformation entity, Map<String, Object> variable) {
        variable.put("drafter", SecurityUtils.getUserId());
    }


    @Override
    public void filterDirtyData() {
        violationInformationDirtyMapper.delete(null);
        List<ViolationInformation> list = violationInformationMapper.selectViolationInformationList(new ViolationInformation());
        //计算需要的线程数 , 假定一个线程处理 500条数据吧
        List<List<ViolationInformation>> lists = GroupUtils.groupData(list, 500);
        //计数器，判断线程是否执行结束
        //CountDownLatch taskLatch = new CountDownLatch(lists.size());
        for (List<ViolationInformation> subList : lists) {
            execute.execute(() -> {
                //执行任务的方法
                super.processRow(subList, null);
                //判断status是 1待提交，2处理中, 且已创建时间大于7天, 则认为是脏数据
                for(ViolationInformation violationInformation : subList) {
                    Integer status = violationInformation.getStatus();
                    if((status != null && (System.currentTimeMillis() - violationInformation.getCreateTime().getTime())/(24*60*60*1000) > 7) && (1 == status || 2 == status)) {
                        ViolationInformationDirty dirty = new ViolationInformationDirty();
                        BeanUtils.copyBeanProp(dirty, violationInformation);
                        dirty.setDirtyReason("超过7天未处理完毕!");
                        violationInformationDirtyMapper.insert(dirty);
                    }
                }
                //taskLatch.countDown();
            });
        }
        //当前线程阻塞，等待计数器置为0, 即线程全部执行完成
        //taskLatch.await();
    }

    /**
     * 定时任务扫描 培训标识为1的数据，且流程状态是已完成的违章举报，创建培训，创建之后更新培训标识字段为2（代表已经创建培训任务）
     */
    @Override
    @Transactional
    public void createTrain() {
        ViolationInformation violationInformation = new ViolationInformation();
        violationInformation.setNeedTrain(1);
        List<ViolationInformation> list = violationInformationMapper.selectViolationInformationList(violationInformation);
        super.processRow(list, null);
        List<ViolationInformation> collect = list.stream().filter(item -> item.getStatus() != null && item.getStatus() == 3).collect(Collectors.toList());
        for (int i = 0; i < collect.size(); i++) {
            String responsible = collect.get(i).getResponsible();
            SysUser sysUser = remoteUserService.getUserById(Long.valueOf(responsible)).getData();
            Long parentId = sysUser.getDept().getParentId();
            //查询部门的安全员
            Map<String,Object> map = new HashMap<>();
            map.put("roleKey", "aqy");
            map.put("parentId", parentId);
            List<Map<String, Object>> data = remoteUserService.selectAdminByRoleAndDept(map).getData();
            if (data.size() != 0) {
                Integer aqyUserId = (Integer)data.get(0).get("userId");

                TrainPlan trainPlan = new TrainPlan();
                trainPlan.setCreateBy(String.valueOf(aqyUserId));
                trainPlan.setAssessmentMethod("2");
                trainPlan.setChooseWay("1");
                trainPlan.setClassHourNumber("1");
                trainPlan.setClassNumber(1);
                trainPlan.setDataDee(new BigDecimal(0));
                trainPlan.setDayNumber(new BigDecimal(1));
                trainPlan.setDeptId(sysUser.getDept().getDeptId());
                trainPlan.setLectureFee(new BigDecimal(0));
                trainPlan.setOtherFee(new BigDecimal(0));
                trainPlan.setPeopleNumber(1);
                trainPlan.setTotalCost(new BigDecimal(0));
                trainPlan.setTrainContent("违章培训");
                trainPlan.setTrainMethod("1");
                trainPlan.setTrainName(collect.get(i).getId() + "违章培训");

                TrainPlanShift shift = new TrainPlanShift();
                shift.setClassDirector(String.valueOf(aqyUserId));
                shift.setClassName("第1班");
                shift.setDept(collect.get(i).getAssociatedDept());
                shift.setLearnerIds(collect.get(i).getResponsible());
                shift.setSchoolHour(new BigDecimal("1"));
                shift.setTrainDay(new BigDecimal("1"));

                ArrayList<TrainPlanShift> trainPlanShifts = new ArrayList<>();
                trainPlanShifts.add(shift);
                trainPlan.setTrainPlanShiftList(trainPlanShifts);

                List<TrainPlanStaff> trainPlanStaffs = new ArrayList<>();
                TrainPlanStaff trainPlanStaff = new TrainPlanStaff();
                trainPlanStaff.setNumber(1);
                trainPlanStaff.setType("违章人员");
                trainPlanStaffs.add(trainPlanStaff);
                trainPlan.setTrainPlanStaffs(trainPlanStaffs);
                trainPlan.setTrainType("4");
                trainPlan.setTrainingFee(new BigDecimal(0));
                trainPlan.setTravelExpenses(new BigDecimal(0));
                trainPlan.setYear(DateUtils.dateTimeNow("YYYY"));
                trainPlanService.insertTrainPlan(trainPlan);
                collect.get(i).setNeedTrain(2);
                violationInformationMapper.updateViolationInformation(collect.get(i));
            }
        }
    }

    @Override
    public List<ViolationInformation> selectViolationInformationListWithOutDataPermission(ViolationInformation violationInformation) {
        List<ViolationInformation> violationInformations = violationInformationMapper.selectViolationInformationListWithOutDataPermission(violationInformation);
        super.processRow(violationInformations, null);
        return violationInformations;
    }


}
